package com.efounder.form.comp.sign;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * Created by zhaopengxiang on 2016/4/6.
 * View实现涂鸦、撤销以及重做功能
 */
public class GraffitiView extends View {
	private Context context;
	private Bitmap mBitmap;
	private Canvas mCanvas;
	private Path mPath;
	private Paint mBitmapPaint;// 画布的画笔
	private Paint mPaint;// 真实的画笔
	private float mX, mY;// 临时点坐标
	private static final float TOUCH_TOLERANCE = 3F;

	public static List<DrawPath> getSavePath() {
		return savePath;
	}

	public static void setSavePath(List<DrawPath> savePath) {
		GraffitiView.savePath = savePath;
	}

	// 保存Path路径的集合,用List集合来模拟栈
	private static List<DrawPath> savePath;
	// 保存已删除Path路径的集合
	private static List<DrawPath> deletePath;
	// 记录Path路径的对象
	private DrawPath dp;
	private int screenWidth, screenHeight;
	private int currentColor = Color.BLACK;
	private int currentSize = 6;
	private int currentStyle = 1;
	private int[] paintColor;// 颜色集合

	private class DrawPath {
		public Path path;// 路径
		public Paint paint;// 画笔
	}

	public GraffitiView(Context context, int w, int h) {
		super(context);
		this.context = context;
		this.setBackgroundResource(android.R.drawable.dialog_holo_light_frame);
		//this.setBackgroundResource();
		screenWidth = w;
		screenHeight = h;
		paintColor = new int[] { Color.RED, Color.BLUE, Color.GREEN,
				Color.YELLOW, Color.BLACK, Color.GRAY, Color.CYAN };
		setLayerType(LAYER_TYPE_SOFTWARE, null);// 设置默认样式，去除dis-in的黑色方框以及clear模式的黑线效果
		initCanvas();
		savePath = new ArrayList<DrawPath>();
		deletePath = new ArrayList<DrawPath>();

		//设置GraffitiView宽高
		ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(w,h);
		setLayoutParams(layoutParams);
	}

	public void initCanvas() {
		setPaintStyle();
		mBitmapPaint = new Paint(Paint.DITHER_FLAG);
		// 画布大小
		mBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
				Bitmap.Config.ARGB_8888);
		mBitmap.eraseColor(Color.argb(0, 0, 0, 0));
		mCanvas = new Canvas(mBitmap); // 所有mCanvas画的东西都被保存在了mBitmap中
		//mCanvas.drawColor(Color.TRANSPARENT);
		//this.setDrawingCacheBackgroundColor(Color.TRANSPARENT);
	}

	// 初始化画笔样式
	private void setPaintStyle() {
		mPaint = new Paint();
		mPaint.setStyle(Paint.Style.STROKE);
		mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘
		mPaint.setStrokeCap(Paint.Cap.ROUND);// 形状
		mPaint.setAntiAlias(true);
		mPaint.setDither(true);
		if (currentStyle == 1) {
			mPaint.setStrokeWidth(currentSize);
			mPaint.setColor(currentColor);
		} else {// 橡皮擦
			mPaint.setAlpha(0);
			mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
			mPaint.setColor(Color.TRANSPARENT);
			mPaint.setStrokeWidth(50);
		}
	}

	@Override
	public void onDraw(Canvas canvas) {
		// canvas.drawColor(0xFFAAAAAA);
		// 将前面已经画过得显示出来
		canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
		if (mPath != null) {
			// 实时的显示
			canvas.drawPath(mPath, mPaint);
		}
	}


	private void touch_start(float x, float y) {
		mPath.moveTo(x, y);
		mX = x;
		mY = y;
	}

	private void touch_move(float x, float y) {
		float dx = Math.abs(x - mX);
		float dy = Math.abs(mY - y);
		if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
			// 从x1,y1到x2,y2画一条贝塞尔曲线，更平滑(直接用mPath.lineTo也可以)
			mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
			// mPath.lineTo(mX,mY);
			mX = x;
			mY = y;
		}
	}

	private void touch_up(float x, float y) {
		if (mX == x && mY == y){
			mPath.lineTo(mX + 0.1f, mY + 0.1f);//+ 0.1f:点一下，即使没有touch_move也要画出一个点
		}else {
			mPath.lineTo(mX,mY);
		}
		mCanvas.drawPath(mPath, mPaint);
		// 将一条完整的路径保存下来(相当于入栈操作)
		savePath.add(dp);
		mPath = null;// 重新置空
	}

	/**
	 * 撤销 撤销的核心思想就是将画布清空， 将保存下来的Path路径最后一个移除掉， 重新将路径画在画布上面。
	 */
	public void undo() {
		if (savePath != null && savePath.size() > 0) {
			DrawPath drawPath = savePath.get(savePath.size() - 1);
			deletePath.add(drawPath);
			savePath.remove(savePath.size() - 1);
			redrawOnBitmap();
		}
	}

	/**
	 * 重做
	 */
	public void redo() {
		if (savePath != null && savePath.size() > 0) {
			savePath.clear();
			redrawOnBitmap();
		}
	}

	private void redrawOnBitmap() {

		initCanvas();
		Iterator<DrawPath> iter = savePath.iterator();
		while (iter.hasNext()) {
			DrawPath drawPath = iter.next();
			mCanvas.drawPath(drawPath.path, drawPath.paint);
		}
		invalidate();// 刷新
	}

	/**
	 * 恢复，恢复的核心就是将删除的那条路径重新添加到savapath中重新绘画即可
	 */
	public void recover() {
		if (deletePath.size() > 0) {
			// 将删除的路径列表中的最后一个，也就是最顶端路径取出（栈）,并加入路径保存列表中
			DrawPath dp = deletePath.get(deletePath.size() - 1);
			savePath.add(dp);
			// 将取出的路径重绘在画布上
			mCanvas.drawPath(dp.path, dp.paint);
			// 将该路径从删除的路径列表中去除
			deletePath.remove(deletePath.size() - 1);
			invalidate();
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float x = event.getX();
		float y = event.getY();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// 每次down下去重新new一个Path
			mPath = new Path();
			// 每一次记录的路径对象是不一样的
			dp = new DrawPath();
			dp.path = mPath;
			dp.paint = mPaint;
			touch_start(x, y);
			invalidate();
			break;
		case MotionEvent.ACTION_MOVE:
			touch_move(x, y);
			invalidate();
			break;
		case MotionEvent.ACTION_UP:
			touch_up(x, y);
			invalidate();
			break;
		}
		return true;
	}

	
	/**
	 * 得到bitmap
	 * @return
	 */
	public Bitmap getBitmap() {
		return mBitmap;
	}

	// 保存到sd卡
	public void saveToSDCard(String path) {
		// 获得系统当前时间，并以该时间作为文件名
		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
		Date curDate = new Date(System.currentTimeMillis());// 获取当前时间
		String str = formatter.format(curDate) + ".png";
		File file = new File(path + File.separator + str);
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
		} catch (Exception e) {
			e.printStackTrace();
		}
		mBitmap.compress(CompressFormat.PNG, 100, fos);
		Log.i("TAG", "图片已保存");
	}

	// 以下为样式修改内容
	// 设置画笔样式
	public void selectPaintStyle(int which) {
		if (which == 0) {
			currentStyle = 1;
			setPaintStyle();
		}
		// 当选择的是橡皮擦时，设置颜色为白色
		if (which == 1) {
			currentStyle = 2;
			setPaintStyle();
		}
	}

	// 设置画笔大小
	public void setPaintSize(int size) {
		
		currentSize = size;
		setPaintStyle();
	}

	// 设置画笔颜色
	public void setPaintColor(int color) {
		currentColor = color;
		setPaintStyle();
	}
	

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO 自动生成的方法存根
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		int heightSize = MeasureSpec.getSize(heightMeasureSpec);
		
		//如果宽度模式为精确模式,将父容器指定的宽度赋给View宽，否则View本身计算空间
		if (widthMode == MeasureSpec.EXACTLY) {
			screenWidth = widthSize;
		} else {
			screenWidth = widthSize;
		}

		//如果高度模式为精确模式,将父容器指定的高度赋给View高，否则View本身计算空间
		if (heightMode == MeasureSpec.EXACTLY) {
			screenHeight = heightSize;
		} else {
			screenHeight = heightSize;
		}
		setMeasuredDimension(screenWidth, screenHeight);
	System.out.println(screenWidth+ screenWidth);
	
	}
}